/*
 * bucket.h
 *
 *  Created on: 27 Apr 2010
 *      Author: osky
 */

#include "c_bucket.h"
#include <stdio.h>

c_bucket::c_bucket (int n_bucket)
        {
        nro_bucket=n_bucket;
        reg_por_bucket=0;
        bits_en_comun=0; /*EXTENSION_INICIAL; */
        espacio_libre=LARGO_BLOQUE - 4 * sizeof(unsigned int) ; /* Le resto los campos de control */
        mem_buffer.set_nro(n_bucket+BLOQUES_TABLA);

        }
        
unsigned int c_bucket::ocupado ()
        {
        
        return reg_por_bucket;
        
        }

void c_bucket::set_bits_en_comun (unsigned int bits)
        {
        bits_en_comun=bits;
        }

unsigned int c_bucket::get_bits_en_comun (void)
        {
        return bits_en_comun;
        }

void c_bucket::get ( unsigned int &g_nro_bucket, unsigned int &g_reg_por_bucket)
        {
        g_nro_bucket = nro_bucket  ;
        g_reg_por_bucket = reg_por_bucket;
        }


int c_bucket::dump_registro (unsigned int nro_reg)
{

int res;

if (nro_reg>reg_por_bucket) res=RES_NOK;

else { printf ("Clave: %d Data:%s\n", registros[nro_reg].get_clave(),registros[nro_reg].get_data());
       res=RES_OK;
     }

return res;

}


int c_bucket::buscar_clave ( unsigned int clave)
         {
         int i=reg_por_bucket;
         int encontrado=-1;

         while (i)
            {
                 #ifdef _DEBUG_
                     printf ("Comparando clave: %d con %d (reg %d) \n", clave, registros[i].get_clave(),i);
                 #endif

            if ( (registros[i-1].get_clave() == clave)  )
                {
                 encontrado=i-1;
                 i=0;
                }
             else i--;

            }

         return encontrado;
         }


int c_bucket::insertar_reg ( c_registro* reg)
        {
        int res;


        if ( reg_por_bucket < MAX_REGISTROS_POR_BUCKET )

    	    {
    	    if ( reg->largo_reg() < espacio_libre)
    		{
    		 registros[reg_por_bucket].copiar(reg);
                 espacio_libre-=reg->largo_reg();
                 res=RES_OK;

                 #ifdef _DEBUG_
     	         printf("Insertado, registro clave: %d longitud: %d  data: %s en bucket: %d posicion %d - Espacio disponible %d\n" ,reg->get_clave(),reg->largo_reg(),reg->get_data(),nro_bucket, reg_por_bucket,espacio_libre);
                 #endif

                 reg_por_bucket++;

                 #ifdef _DEBUG_
                 printf ("Registros por bucket: %d \n",reg_por_bucket);
                 #endif

    		}
                 else  { 
                           #ifdef _DEBUG_
                           printf(" BLOQUE LLENO - SUPERA ESPACIO MAXIMO DIPOSNIBLE POR BUCKET\n");
	                   #endif 
                          
                          res=RES_SUPERA_MAX_ESPACIO;
                       }

    	    } else { 
                     #ifdef _DEBUG_    	    
    	             printf(" BLOQUE LLENO - SUPERA CANTIDAD MAXIMA DE REG POR BLOQUE \n");
	             #endif
	                 	             
    	             res=RES_SUPERA_MAX_REG; /* BLOQUE LLENO - SUPERA CANTIDAD MAXIMA DE REG POR BLOQUE */
    	           }



        return res;
        }



int c_bucket::dividir ( c_bucket* bucket_0, c_bucket* bucket_1)
    {

    int resultado;
    unsigned int clave;
    unsigned int bit_split = get_bits_en_comun();
    unsigned int mascara = 1 << (15-bit_split);

   #ifdef _DEBUG_    	   
    printf ("Dividiendo el bucket: %d utilizandoe el bit %d mascara: %d \n", nro_bucket, bit_split, mascara );
   #endif		

    if  ( bit_split <=  MAX_BITS_HASH )
    {

    for (unsigned int i=0; i< reg_por_bucket; i++)
	{
	   clave = registros [i] . get_clave();

	   if (clave&mascara) { bucket_1->insertar_reg(&registros [i]);

	                        }
	   else 		{ bucket_0->insertar_reg(&registros [i]);

	                        }

	}

	bucket_0->set_bits_en_comun(bit_split+1);
	bucket_1->set_bits_en_comun(bit_split+1);

    resultado=bit_split;
    
    } else  { resultado = RES_SUPERA_MAX_DIV;  /* NO SE PUEDE DIVIDIR MAS */
    
            }

    return resultado;
    }




int c_bucket::eliminar_dato ( unsigned int clave)
         {

         unsigned int encontrado=RES_NOK;


         for ( unsigned int i=0 ; i < reg_por_bucket  ; i++)

		{
    		     #ifdef _DEBUG_ 
    	             printf ("(Eliminado...) Comparando clave: %d con %d (reg %d)  registros en el bucket: %d \n", clave, registros[i].get_clave(),i,reg_por_bucket);
		     #endif


                    /* SI TODAVIA NO LO ENCONTRO */


                    if (registros[i].get_clave() == clave)   { encontrado=RES_OK;
                			    		       #ifdef _DEBUG_ 
                					       printf("Encontrado!!!\n");
							       #endif
                					       
                                                              }

                    else  /* Si ya lo encontro mueve los siguientes a la posicion anterior */
                         {
                            if(encontrado) registros[i-1]=registros[i];
                         }

    	     }



         if (encontrado) reg_por_bucket--;

         return encontrado;
         }



int c_bucket::save()
	{
	 int resultado=1;

	 mem_buffer.set_pos(0);

	 resultado&=mem_buffer.add (nro_bucket);
	 resultado&=mem_buffer.add (reg_por_bucket);
	 resultado&=mem_buffer.add (bits_en_comun);
	 resultado&=mem_buffer.add (espacio_libre);

	    #ifdef _DEBUG_
	 printf ("Serializando bucket[%d] registros: %d\n",nro_bucket,reg_por_bucket);
	   #endif

	 for (unsigned int i=0;i<reg_por_bucket;i++)
	    {
	    #ifdef _DEBUG_
	    printf ("Serializando registro[%d]\n",i);
	    #endif

	    registros[i].serializar(&mem_buffer);
	    }

	 mem_buffer.save();

	 return resultado;
	}


int c_bucket::load ()
    {
    int resultado=1;

         if( mem_buffer.load() == 1)  /** SI FUE CORRECTAMENTE LEIDO **/

         {

         c_registro reg_aux;
         mem_buffer.set_pos(0);

	 resultado&=mem_buffer.get (&nro_bucket);
	 resultado&=mem_buffer.get (&reg_por_bucket);
	 resultado&=mem_buffer.get (&bits_en_comun);
	 resultado&=mem_buffer.get (&espacio_libre);

	 #ifdef _DEBUG_
	 printf ("c_bucket.load nro_bucket: %d  reg_por_bucket: %d \n", nro_bucket, reg_por_bucket);
	 #endif

	 for (unsigned int i=0;i<reg_por_bucket;i++)
	    {
	    #ifdef _DEBUG_
	    printf ("Deserializando registro[%d]\n",i);
	    #endif
	    reg_aux.deserializar(&mem_buffer);
	    registros[i].copiar(&reg_aux);
	    }


         mem_buffer.set_pos(0);


         }

    return resultado;
    }


void c_bucket::dump (FILE* handler)

         {

            unsigned int clave_hash;
            
            if (reg_por_bucket)
    	        {    
    	        fprintf (handler,"bucket #%d Cantidad de registros: %d espacio libre: %d \n Claves: ", nro_bucket, reg_por_bucket, espacio_libre);	

                for (unsigned int i=0;i<reg_por_bucket;i++)
		    {
		    clave_hash= registros[i].get_clave();
		    fprintf(handler,"%d (%d); ", invertir_bits(clave_hash) , clave_hash);

		    }
		    fprintf (handler,"\n");
		}

         }

